﻿using System;
using System.Collections.Generic;
using System.Text;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Display;

namespace GISCommon.Business
{
    public class MeasureToolsHelper
    {
        #region 变量声明

        /// <summary>
        /// 描述：地图控件

        /// </summary>
        private AxMapControl m_pMapControl;

        /// <summary>
        /// 描述：总距离长度

        /// </summary>
        private double m_Distance = 0;

        /// <summary>
        /// 描述：鼠标移动时用的临时线段的距离

        /// </summary>
        private double m_tmpDistance = 0;

        /// <summary>
        /// 描述：前一个点
        /// </summary>
        private ESRI.ArcGIS.Geometry.IPoint m_pPoint=null;

        /// <summary>
        /// 描述：前一个线段元素

        /// </summary>
        private IElement m_preElement = null;

        /// <summary>
        /// 描述：前一个TextElement
        /// </summary>
        private IElement m_TextElement = null;

        /// <summary>
        /// 描述：指示是否开始测量

        /// </summary>
        private bool m_blnIsMeasure = false;

        #endregion

        #region 对外函数

        /// <summary>
        /// 描述：调用前的初始化
        /// </summary>
        /// <param name="vMapControl">地图控件</param>
        public void Initial(AxMapControl vMapControl)
        {
            try
            {
                //Console.WriteLine("开始调用Initial函数");

                //给MapControl赋值

                m_pMapControl = vMapControl;

                //事件声明
                this.m_pMapControl.OnDoubleClick += new ESRI.ArcGIS.Controls.IMapControlEvents2_Ax_OnDoubleClickEventHandler(this.m_pMapControl_OnDoubleClick);
                this.m_pMapControl.OnMouseUp += new ESRI.ArcGIS.Controls.IMapControlEvents2_Ax_OnMouseUpEventHandler(this.m_pMapControl_OnMouseUp);
                this.m_pMapControl.OnMouseMove += new ESRI.ArcGIS.Controls.IMapControlEvents2_Ax_OnMouseMoveEventHandler(this.m_pMapControl_OnMouseMove);

                //Console.WriteLine("调用Initial函数结束");
                //Console.WriteLine();
            }
            catch (Exception ex)
            {
                SysCommon.Global.mainLog.Error("调用出错", ex);
            }
        }

        /// <summary>
        /// 描述：开始调用量测功能

        /// </summary>
        /// <returns></returns>
        public bool StartMeasure()
        {
            try
            {
                m_blnIsMeasure = true;
                //清理MapControl的Tool
                m_pMapControl.CurrentTool = null;
                //改变鼠标形状
                m_pMapControl.MousePointer = esriControlsMousePointer.esriPointerPencil;
                return true;
            }
            catch (Exception ex)
            {
                SysCommon.Global.mainLog.Error("调用StartMeasure出错！", ex);
                return false;
            }
        }

        /// <summary>
        /// 描述：结束调用量测

        /// </summary>
        /// <returns></returns>
        public bool StopMeasure()
        {
            try
            {
                this.DeleteAllElememts();
                m_PolylinePointCollection.RemovePoints(0, m_PolylinePointCollection.PointCount);
                m_Distance = 0;
                m_blnIsMeasure =false;
                m_preElement = null;
                m_TextElement = null;
                m_pPoint = null;
                m_tmpDistance = 0;
                //改变鼠标形状
                m_pMapControl.MousePointer = esriControlsMousePointer.esriPointerDefault;
                return true;
            }
            catch (Exception ex)
            {
                SysCommon.Global.mainLog.Error("调用StopMeasure出错！", ex);
                return false;
            }
        }
        
        #endregion

        #region 私有方法

        /// <summary>
        /// 描述：响应鼠标按下事件处理

        /// </summary>
        /// <param name="x">鼠标所在点的经度坐标</param>
        /// <param name="y">鼠标所在点的纬度坐标</param>
        private void OnMouseUp(double x, double y)
        {
            try
            {
                //bool blnMousePointerChanged = this.IsMousePointerChanged();
                //if (blnMousePointerChanged)
                //{
                //    return;
                //}

                if (m_blnIsMeasure)
                {
                    m_preElement = new TextElementClass();
                    if (m_pPoint == null)
                    {
                        m_pPoint = this.ConvertToPoint(x, y);
                    }
                    else
                    {
                        ESRI.ArcGIS.Geometry.IPoint pt2 = this.ConvertToPoint(x, y);
                        if (pt2 != null)
                        {
                            m_Distance += this.CalculateDistance(m_pPoint, pt2);                            
                            this.DrawLine(m_pPoint, pt2);
                            m_preElement = null;
                            m_pPoint = pt2;
                            pt2 = null;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                SysCommon.Global.mainLog.Error("调用OnMouseUp出错！", ex);
            }
        }

        /// <summary>
        /// 描述：响应鼠标移动事件处理

        /// </summary>
        /// <param name="x">鼠标所在点的经度坐标</param>
        /// <param name="y">鼠标所在点的纬度坐标</param>
        private void OnMouseMove(double x, double y)
        {
            try
            {
                //bool blnMousePointerChanged = this.IsMousePointerChanged();
                //if (blnMousePointerChanged)
                //{
                //    return;
                //}

                if (m_blnIsMeasure && m_pPoint != null)
                {
                    ESRI.ArcGIS.Geometry.IPoint pt = this.ConvertToPoint(x, y);
                    if (pt != null)
                    {
                        m_tmpDistance = this.CalculateDistance(m_pPoint, pt);
                        double distance = (m_tmpDistance + m_Distance) * 28.3465 * 3600;
                        if (m_preElement == null)
                        {
                            this.DrawLine(m_pPoint, pt);                            
                        }
                        else
                        {
                            this.DeleteElement(m_preElement);
                            this.DrawLine(m_pPoint, pt);
                        }
                        this.DrawText(pt,"当前总长度：" + distance.ToString("0") + "(米)");
                        //Console.WriteLine("----------------------------------------");
                        //Console.WriteLine(distance.ToString());
                        //Console.WriteLine("----------------------------------------");
                        pt = null;
                    }
                }
            }
            catch (Exception ex)
            {
                SysCommon.Global.mainLog.Error("调用OnMouseMove函数出错！", ex);
            }
        }

        private void OnDoubleClick(double x, double y)
        {
            try
            {
                //bool blnMousePointerChanged = this.IsMousePointerChanged();
                //if (blnMousePointerChanged)
                //{
                //    return;
                //}

                if (m_blnIsMeasure)
                {
                    //计算距离
                    if (m_pPoint != null)
                    {
                        ESRI.ArcGIS.Geometry.IPoint pt = this.ConvertToPoint(x, y);
                        m_Distance += this.CalculateDistance(m_pPoint, pt);
                        pt = null;
                        m_pPoint = null;
                    }
                    //提示
                    double dis = m_Distance * 28.2 * 3600;
                    System.Windows.Forms.MessageBox.Show("量算长度结果：" + dis.ToString("0000")+"(米)");
                    m_Distance = 0;
                    m_tmpDistance = 0;
                    //清楚线段
                    //this.DeleteAllElememts();
                    //调用结束
                    //m_blnIsMeasure = false;
                    
                    this.StopMeasure();
                }
            }
            catch (Exception ex)
            {
                SysCommon.Global.mainLog.Error("调用OnDoubleClick函数出错！！", ex);
            }
        }

        /// <summary>
        /// 描述：计算两点间距离
        /// </summary>
        /// <param name="pt1">点对象</param>
        /// <param name="pt2">点对象</param>
        /// <returns>距离</returns>
        private double CalculateDistance(ESRI.ArcGIS.Geometry.IPoint pt1,ESRI.ArcGIS.Geometry.IPoint pt2)
        {
            try
            {
                //Console.WriteLine("开始调用CalculateDistance方法");

                IMap pMap = m_pMapControl.ActiveView.FocusMap;
                double distance = 0;
                if (pMap != null)
                {
                    distance = pMap.ComputeDistance(pt1, pt2);
                }
                else
                {
                    //计算失败
                    Console.WriteLine("当前视图为空！");
                }
                pMap = null;                

                //Console.WriteLine("调用CalculateDistance方法结束");
                //Console.WriteLine();

                return distance;
            }
            catch (Exception ex)
            {
                SysCommon.Global.mainLog.Error("调用CalculateDistance方法出错，", ex);
                return 0;
            }
        }

        /// <summary>
        /// 画在地图上的路线的点集合
        /// </summary>
        ESRI.ArcGIS.Geometry.IPointCollection m_PolylinePointCollection =
            new ESRI.ArcGIS.Geometry.PolylineClass();

        /// <summary>
        /// 描述：画线段
        /// </summary>
        /// <param name="pt1">起点</param>
        /// <param name="pt2">终点</param>
        private void DrawLine(ESRI.ArcGIS.Geometry.IPoint pt1, ESRI.ArcGIS.Geometry.IPoint pt2)
        {
            try
            {
                /*
                //Console.WriteLine("开始调用DrawLine函数");
                //m_pMapControl.ActiveView.GraphicsContainer.DeleteAllElements();

                //转换成Polyline
                ESRI.ArcGIS.Geometry.IPolyline pPolyline = new ESRI.ArcGIS.Geometry.PolylineClass();
                pPolyline.FromPoint = pt1;
                pPolyline.ToPoint = pt2;

                //颜色
                IRgbColor pRgb = new RgbColorClass();
                pRgb.Blue = 255;

                //Symbol
                ISimpleLineSymbol pSymbol = new SimpleLineSymbolClass();
                pSymbol.Color = pRgb;
                pSymbol.Width = 1.2;

                //Line element
                ILineElement pLineElement = new LineElementClass();
                pLineElement.Symbol = pSymbol;

                //声明Element变量
                IElement pElement = (IElement)pLineElement;
                pElement.Geometry = pPolyline;
                m_pMapControl.ActiveView.GraphicsContainer.AddElement(pElement, 0);

                //refresh
                object ep = System.Reflection.Missing.Value;
                m_pMapControl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, pElement, pElement.Geometry.Envelope);

                //set the current element as the previous element
                m_preElement = pElement;

                //Console.WriteLine("调用DrawLine函数结束");
                //Console.WriteLine();

                 * */

                object obj = System.Reflection.Missing.Value;
                m_PolylinePointCollection.AddPoint(pt2, ref obj, ref obj);
                GISCommon.Tools.Drawing.DrawPolyline(m_pMapControl, (ESRI.ArcGIS.Geometry.IPolyline)m_PolylinePointCollection,
                    0, 0, 255, 1);

            }        
            catch(Exception ex)
            {
                SysCommon.Global.mainLog.Error("调用DrawLine出错！", ex);
            }
        }

        /// <summary>
        /// 描述：根据坐标点创建点对象

        /// </summary>
        /// <param name="x">经度坐标</param>
        /// <param name="y">纬度坐标</param>
        /// <returns>点对象</returns>
        private ESRI.ArcGIS.Geometry.IPoint ConvertToPoint(double x, double y)
        {
            try
            {
                ESRI.ArcGIS.Geometry.IPoint pPoint = new ESRI.ArcGIS.Geometry.PointClass();
                pPoint.PutCoords(x, y);

                return pPoint;
            }
            catch (Exception ex)
            {
                SysCommon.Global.mainLog.Error("调用ConvertToPoint出错！", ex);
                return null;
            }
        }

        private void DeleteElement(IElement pElement)
        {
            try
            {
                /*
                m_pMapControl.ActiveView.GraphicsContainer.DeleteElement(pElement);

                esriViewDrawPhase p = esriViewDrawPhase.esriViewGraphics;
                m_pMapControl.ActiveView.PartialRefresh(p, pElement, pElement.Geometry.Envelope);
                //m_pMapControl.Refresh(p, pElement, pElement.Geometry.Envelope);
                 * */

                m_PolylinePointCollection.RemovePoints(m_PolylinePointCollection.PointCount - 1, 1);

                GISCommon.Tools.Drawing.DrawPolyline(m_pMapControl, (ESRI.ArcGIS.Geometry.IPolyline)m_PolylinePointCollection,
                    0, 0, 255, 1);
            }
            catch (Exception ex)
            {
                SysCommon.Global.mainLog.Error("调用DeleteElement出错！", ex);
            }
        }

        private void DeleteAllElememts()
        {
            try
            {
                m_pMapControl.ActiveView.GraphicsContainer.DeleteAllElements();
                m_preElement = null;

                esriViewDrawPhase p = esriViewDrawPhase.esriViewGraphics;
                m_pMapControl.ActiveView.PartialRefresh(p,null,null);
                //m_pMapControl.Refresh(p, null, null);
            }
            catch (Exception ex)
            {
                SysCommon.Global.mainLog.Error("调用DeleteAllElememts出错！", ex);
            }
        }

        private void DrawText(ESRI.ArcGIS.Geometry.IPoint pPoint,string Text)
        {
            try
            {
                ITextElement pTextElement = new TextElementClass();
                pTextElement.Text = Text;
                IElement pElement = (IElement)pTextElement;
                pElement.Geometry = pPoint;
                if (m_TextElement != null)
                    m_pMapControl.ActiveView.GraphicsContainer.DeleteElement(m_TextElement);
                m_pMapControl.ActiveView.GraphicsContainer.AddElement(pElement, 0);
                m_TextElement = pElement;
                //m_pMapControl.Refresh(esriViewDrawPhase.esriViewGraphics, null, null);
                m_pMapControl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics,null, null);
            }
            catch (Exception ex)
            {
                SysCommon.Global.mainLog.Error("调用DrawText出错！", ex);
            }
        }
               
        #endregion

        #region 属性变量

        /// <summary>
        /// 描述：要帮定的地图控件

        /// </summary>
        public AxMapControl MapControl
        {
            get { return m_pMapControl; }
            set { m_pMapControl = value; }
        }
        #endregion

        #region 事件函数

        private void m_pMapControl_OnDoubleClick(object sender, IMapControlEvents2_OnDoubleClickEvent e)
        {
            this.OnDoubleClick(e.mapX, e.mapY);
        }

        private void m_pMapControl_OnMouseUp(object sender, IMapControlEvents2_OnMouseUpEvent e)
        {
            this.OnMouseUp(e.mapX, e.mapY);
        }

        private void m_pMapControl_OnMouseMove(object sender, IMapControlEvents2_OnMouseMoveEvent e)
        {
            this.OnMouseMove(e.mapX, e.mapY);
        }

        #endregion

    }
}
